﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using FinPlusInterfaces;

namespace FinPlusAssembler
{
    public static class FinPlusStateInject
    {
        //public
        public static IPods ExtractState(this IPod pod, string user = "", bool test = false, IPods states = null)
        {
            states = states ?? IOC.New<IPods>() ;
            user = string.IsNullOrEmpty(user) ? Environment.UserName : user;

            try
            {
                var parent = pod.ExtractState(user, test);
                if (parent != null) 
                    states.Add(parent, true, false);

                var model = pod.Property("Adapter");
                if (model == null) 
                    return states;

                foreach (var child in ((IPods)model).Values)
                    child.ExtractState(user, test, states);

                return states;
            }
            catch 
            {
                return states;
            }
        }

        public static void InjectState(this IPod pod, string statesPath, bool async = true)
        {
            try
            {
                pod.InjectState(IOC.New<IPods>(statesPath.EndsWith(FileType.state.ToString()) ? statesPath : string.Format("{0}.{1}", statesPath, FileType.state.ToString())));
            }
            catch
            {
                return;
            }
        }

        public static void InjectState(this IPod pod, IPods states)
        {
            try
            {
                var Id = pod.Property(PodField.Id.ToString());
                if (Id == null) 
                    return;

                foreach (var state in states.Values)
                    if (Id.ToString() == state[PodField.Id.ToString()].ToString())
                        InjectState(pod, state);


                var model = pod.Property("Adapter");
                if (model == null) 
                    return;

                foreach (var child in ((IPods)model).Values)
                    child.InjectState(states);
            }
            catch 
            {
                return;
            }
        }

        public static void InjectState(this IPod pod, IPod states)
        {
            foreach (var state in states)
                if (!state.Name.EnumIsDefined<PodField>())
                    pod.InjectState(state);
        }

        public static void InjectState(this IPod pod, IBean state)
        {
            try
            {
                if (pod.HasProperty(state.Name))
                {
                    var pInfo = pod.Object.GetType().GetProperty(state.Name);
                    pInfo.SetValue(pod.Object, state.Object, null);
                }
            }
            catch
            {
                return;
            }
        }

        //private
        private static IPod ExtractState(this IPod pod, string user, bool test)
        {
            try
            {
                var Id = pod.Property(PodField.Id.ToString());
                if (Id == null) 
                    return null;

                var states = pod.Object.GetType().StatePropertys(test);
                if (states == null) 
                    return null;

                var statePod = IOC.New<IPod>(pod.Object.GetType().Name, Id.ToString(), user);
                var pos = 4;
                foreach (var state in states)
                {
                    var bean = pod.ExtractState(state, pos, user);
                    if (bean != null)
                    {
                        statePod.TryAdd(bean);
                        pos++;
                    }
                }

                //if has state return pod
                return pos > 4 ? statePod : null;
            }
            catch 
            {
                return null;
            }
        }

        private static IBean ExtractState(this IPod pod, string state, int pos, string user)
        {
            try
            {
                var value = pod.Property(state);
                if (value == null) 
                    return null;

                var bean = IOC.New<IBean>(pos, pod.Id, state, value, DateTime.Now, user);
                return bean;
            }
            catch 
            {
                return null;
            }
        }
     }
}
